<template>
  <div class="app-container">
    <!-- 步骤条 -->
    <div class="steps-container">
      <el-steps :active="currentStep" align-center>
        <el-step title="上传文件" description="将文件上传到临时分区"></el-step>
         <el-step title="创建任务" description="创建上传任务"></el-step>
        <el-step title="分发文件" description="将文件分发到各服务器"></el-step>
        <el-step title="上传完成" description="释放资源"></el-step>
      </el-steps>
    </div>

    <el-row :gutter="20">
      <!-- 左侧表单区域 -->
      <el-col :span="12">
        <el-card class="box-card">
          <template #header>
            <div class="card-header">
              <span>上传配置</span>
            </div>
          </template>
          
          <el-form :model="form" :rules="rules" ref="formRef" label-width="100px">
            <el-form-item label="上传路径" prop="remotePath">
              <el-input v-model="form.remotePath" placeholder="请输入上传路径">
                <template #prepend>路径:</template>
              </el-input>
              <div class="el-form-item__tip">路径必须真实存在，且有写入权限。</div>
            </el-form-item>
            
            <el-form-item label="主机组" prop="hostGroupId">
              <el-tree-select
                v-model="form.hostGroupId"
                :data="groupTree"
                check-strictly
                :props="{ label: 'name', children: 'children' }"
                :render-after-expand="false"
                placeholder="请选择主机组"
                style="width: 100%"
              />
            </el-form-item>
            
            <el-form-item label="备注说明" prop="description">
              <el-input
                v-model="form.description"
                type="textarea"
                :rows="2"
                placeholder="请输入上传任务描述"
                maxlength="255"
                show-word-limit
              />
            </el-form-item>
            
            <el-form-item label="上传文件">
              <div class="upload-actions">
                <el-upload
                  action=""
                  :multiple="true"
                  :show-file-list="false"
                  :auto-upload="false"
                  :on-change="handleFileChange"
                >
                  <el-button type="primary" icon="el-icon-document-add">选择文件</el-button>
                </el-upload>
                
                <el-button icon="el-icon-delete" @click="clearFiles">清空列表</el-button>
              </div>
            </el-form-item>
            
            <el-form-item>
              <el-button type="primary" @click="submitUpload" :loading="uploading" size="large">
                {{ uploading ? '上传中...' : '开始上传' }}
              </el-button>
              <el-button @click="resetForm" :disabled="uploading" size="large">重置</el-button>
            </el-form-item>
          </el-form>
        </el-card>
      </el-col>

      <!-- 右侧文件列表 -->
      <el-col :span="12">
        <el-card class="box-card">
          <template #header>
            <div class="card-header">
              <span>文件列表 ({{ fileList.length }}个文件)</span>
              <span>总大小: {{ formatFileSize(totalSize) }}</span>
            </div>
          </template>
          
         <!-- 文件列表部分修改 -->
  <div class="file-list-container">
    <el-scrollbar v-if="fileList.length > 0" max-height="300px">
      <div 
        class="file-item" 
        v-for="(file, index) in fileList" 
        :key="file.id"
      >
        <el-icon class="file-icon"><Document /></el-icon>
        <div class="file-info">
          <div class="file-name">{{ file.name }}</div>
          <div class="file-size">{{ formatFileSize(file.size) }}</div>
        </div>
        <!-- 添加状态显示 -->
        <div class="file-status">
          <el-icon v-if="file.status === 'success'" color="#67C23A" class="status-icon">
            <SuccessFilled />
          </el-icon>
          <el-icon v-else-if="file.status === 'error'" color="#F56C6C" class="status-icon">
            <CircleCloseFilled />
          </el-icon>
          <el-progress 
            v-else-if="file.status === 'uploading'" 
            :percentage="file.progress || 0" 
            :width="40"
            type="circle" 
          />
          <span v-else class="status-text">{{ getFileStatusText(file.status) }}</span>
        </div>
        <el-button
          size="small"
          type="danger"
          text
          icon="el-icon-close"
          @click="removeFile(index)"
        />
      </div>
    </el-scrollbar>
            
            <div v-else class="no-file-tip">
              <el-divider>
                <el-icon><Document /></el-icon>
              </el-divider>
              <p>请选择要上传的文件</p>
            </div>
          </div>
        </el-card>
  <!-- 服务器进度面板 -->
  <el-card class="box-card server-card" v-if="uploading || serverProgress.length > 0">
    <template #header>
      <div class="card-header">
        <span>服务器上传进度</span>
        <el-button v-if="!uploading" size="small" @click="clearServerProgress">清空进度</el-button>
      </div>
    </template>
    
    <div class="server-progress-list">
      <div v-for="host in serverProgress" :key="host.hostId" class="server-item">
        <div class="server-info">
          <span class="server-name">{{ host.hostName }}</span>
          <span class="server-address">{{ host.hostAddress }}</span>
          <el-tag :type="getStatusType(host.status)" size="small">
            {{ getStatusText(host.status) }}
          </el-tag>
        </div>
        
        <div class="file-progress-list">
          <div v-for="file in host.files" :key="file.fileId" class="file-progress-item">
            <div class="file-name">{{ file.fileName }}</div>
            <div class="file-status">
              <el-tooltip 
                v-if="file.status === 'failed' && file.errorMessage" 
                :content="file.errorMessage"
                placement="top"
              >
                <el-tag :type="getStatusType(file.status)" size="small">
                  {{ getStatusText(file.status) }}
                </el-tag>
              </el-tooltip>
              <el-tag v-else :type="getStatusType(file.status)" size="small">
                {{ getStatusText(file.status) }}
              </el-tag>
            </div>
          </div>
        </div>
      </div>
    </div>
  </el-card>
  </el-col>
    </el-row> 
  </div>
</template>

<script setup>
import { ref, reactive, computed, onMounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Document } from '@element-plus/icons-vue'
import { listGroup } from "@/api/os/group"
import {getUploadProgress,createUploadTask ,uploadTempMulti} from "@/api/exec/file"

// 获取若依实例
const { proxy } = getCurrentInstance()

// 当前步骤
const currentStep = ref(0)

// 表单数据
const form = reactive({
  remotePath: '',
  hostGroupId: '',
  description: ''
})
// 获取文件状态文本
const getFileStatusText = (status) => {
  const statusMap = {
    'waiting': '等待上传',
    'uploading': '上传中',
    'success': '成功',
    'error': '失败',
    'pending': '待处理'
  }
  return statusMap[status] || status
}
// 表单验证规则
const rules = {
  remotePath: [
    { required: true, message: '请输入上传路径', trigger: 'blur' }
  ],
  hostGroupId: [
    { required: true, message: '请选择主机组', trigger: 'change' }
  ]
}

// 文件列表相关
const fileList = ref([])
const totalSize = computed(() => {
  return fileList.value.reduce((total, file) => total + file.size, 0)
})

// 上传状态相关
const uploading = ref(false)
const uploadTaskId = ref(null)
const progressInterval = ref(null)

// 主机组树数据
const groupTree = ref([])

// 服务器进度
const serverProgress = ref([])

// 获取主机组树
const getGroupTree = () => {
  listGroup().then(response => {
    if (response.code === 200) {
      groupTree.value = response.data
      // 确保数据结构正确，el-tree-select 需要正确的 value 和 label
      const processTreeData = (nodes) => {
        return nodes.map(node => ({
          ...node,
          value: node.id, // 用于 v-model 绑定的值
          label: node.name, // 用于显示的标签
          children: node.children ? processTreeData(node.children) : []
        }))
      }
      groupTree.value = processTreeData(response.data)
    } else {
      ElMessage.error("获取分组列表失败")
    }
  }).catch(error => {
    console.error("获取分组列表失败:", error)
    ElMessage.error("获取分组列表失败")
  })
}


// 格式化文件大小
const formatFileSize = (bytes) => {
  if (bytes === 0) return '0 B'
  const k = 1024
  const sizes = ['B', 'KB', 'MB', 'GB', 'TB']
  const i = Math.floor(Math.log(bytes) / Math.log(k))
  return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
}

// 文件选择处理
const handleFileChange = (file) => {
  const newFile = {
    id: Math.random().toString(36).substr(2, 9),
    name: file.name,
    size: file.size,
    raw: file.raw
  }
  
  // 防止重复添加
  if (!fileList.value.some(f => f.name === newFile.name && f.size === newFile.size)) {
    fileList.value.push(newFile)
  }
}

// 移除文件
const removeFile = (index) => {
  fileList.value.splice(index, 1)
}

// 清空文件列表
const clearFiles = () => {
  if (fileList.value.length === 0) return
  
  ElMessageBox.confirm(
    '确定要清空所有已选文件吗?',
    '确认清空',
    {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning'
    }
  ).then(() => {
    fileList.value = []
  })
}

// 修改状态映射
const getStatusText = (status) => {
  const statusMap = {
    'waiting': '等待中',
    'uploading': '上传中',
    'finished': '已完成',
    'partial_success': '部分成功',
    'failed': '失败',
    'canceled': '已取消'
  }
  return statusMap[status] || status
}

const getStatusType = (status) => {
  const statusMap = {
    'waiting': 'info',
    'uploading': 'warning',
    'finished': 'success',
    'partial_success': 'success',
    'failed': 'danger',
    'canceled': 'info'
  }
  return statusMap[status] || ''
}

// 提交上传
const submitUpload = async () => {
  try {
      uploading.value = true
  
    // 先上传到临时区域
    const uploadedFiles = await uploadFilesToTemp(fileList.value);
    if (uploadedFiles.length === 0) {
      throw new Error('没有文件上传成功，无法创建任务');
      return;
    }
      currentStep.value = 1 // 先进入创建任务步骤
    // 然后创建任务
    const response = await createTaskRequest(form, uploadedFiles);
    if (response.code === 200) {
      currentStep.value = 2; // 进入分发文件步骤
      ElMessage.success('任务创建成功');
      // 开始轮询任务进度
      startProgressPolling(response.data.taskId);
    }
  } catch (error) {
        uploading.value = false
    ElMessage.error('上传失败: ' + error.message);
  }
};


  // 1. 先上传所有文件到临时区域
const uploadFilesToTemp = async (files) => {
  const uploadedFiles = [];
  
  // 创建FormData并添加所有文件
  const formData = new FormData();
  files.forEach(file => {
    formData.append('files', file.raw); // 使用 'files' 作为字段名
    file.status = 'uploading'
    file.progress = 0
  });

  try {
    const response = await uploadTempMulti(formData, {
      onUploadProgress: (progressEvent) => {
        // 计算总体进度
        const percent = Math.round((progressEvent.loaded * 100) / progressEvent.total);
        // 更新所有文件的进度
        files.forEach(file => {
          file.progress = percent
        });
      }
    });
    
    if (response.code === 200) {
      // 处理上传结果
      response.data.files.forEach((result, index) => {
        if (result.status === 'success') {
          files[index].status = 'success'
          uploadedFiles.push({
            ...result,
            originalFile: files[index]
          });
        } else {
          files[index].status = 'error'
          console.error(`文件 ${result.fileName} 上传失败:`, result.error)
        }
      });
    }
  } catch (error) {
    // 所有文件标记为失败
    files.forEach(file => {
      file.status = 'error'
    });
    console.error('文件上传失败:', error)
    throw error
  }
  
  return uploadedFiles;
};
// 2. 然后创建上传任务
const createTaskRequest = async (formData, uploadedFiles) => {
  const taskData = {
    remotePath: formData.remotePath,
    hostGroupId: formData.hostGroupId,
    description: formData.description,
    files: uploadedFiles.map(file => ({
      fileId: file.fileId,
      name: file.fileName,
      size: file.fileSize,
      localPath: file.tempFilePath // 使用localPath字段
    }))
  };
  
  return await createUploadTask(taskData);
};


// 开始轮询进度（修正函数）
// 开始轮询进度
const startProgressPolling = (taskId) => {
  uploadTaskId.value = taskId;
  uploading.value = true;
  currentStep.value = 2; // 进入分发文件步骤
  
  progressInterval.value = setInterval(() => {
    if (!uploadTaskId.value) return
    
    getUploadProgress(uploadTaskId.value).then(response => {
      if (response.code === 200) {
        const progressData = response.data
        
        // 更新服务器进度 - 保留历史数据
        if (progressData.hosts && progressData.hosts.length > 0) {
          serverProgress.value = progressData.hosts
        }
        
        // 更新步骤
        if (progressData.currentStep) {
          currentStep.value = progressData.currentStep
        }
        
        // 检查是否完成
        const finishedStatuses = ['finished', 'completed', 'failed', 'canceled', 'partial_success']
        if (finishedStatuses.includes(progressData.status)) {
          clearInterval(progressInterval.value)
          uploading.value = false
          currentStep.value = 3 // 进入完成步骤
          
          if (progressData.status === 'finished' || progressData.status === 'completed') {
             currentStep.value = 4; // 全部高亮
            ElMessage.success('上传任务已完成')
          } else if (progressData.status === 'failed') {
            ElMessage.error('上传任务失败')
          } else if (progressData.status === 'partial_success') {
            ElMessage.warning('上传任务部分成功')
          }
        }
      }
    }).catch(error => {
      console.error('获取进度失败:', error)
    })
  }, 2000) // 每2秒轮询一次
}
// 重置表单
const resetForm = () => {
  ElMessageBox.confirm(
    '确定要重置表单吗?所有已填写的内容和文件列表将被清空。',
    '确认重置',
    {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning'
    }
  ).then(() => {
    proxy.$refs.formRef.resetFields()
    fileList.value = []
    uploading.value = false
    currentStep.value = 0
    serverProgress.value = []
    
    if (progressInterval.value) {
      clearInterval(progressInterval.value)
      progressInterval.value = null
    }
    
    ElMessage.success('表单已重置')
  })
}

// 添加清空进度的方法
const clearServerProgress = () => {
  ElMessageBox.confirm(
    '确定要清空服务器进度显示吗?',
    '确认清空',
    {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning'
    }
  ).then(() => {
    serverProgress.value = []
    ElMessage.success('进度已清空')
  })
}

onMounted(() => {
  // 初始化远程路径默认值
  form.remotePath = '/home/uploads'
  // 获取主机组树
  getGroupTree()
})

// 组件卸载时清理定时器
onUnmounted(() => {
  if (progressInterval.value) {
    clearInterval(progressInterval.value)
  }
})
</script>

<style scoped>
.app-container {
  padding: 20px;
}

/* 步骤条样式 */
.steps-container {
  background: #fff;
  padding: 20px;
  margin-bottom: 20px;
  border-radius: 4px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}

:deep(.el-step__description) {
  font-size: 13px;
  color: #909399 !important;
  margin-top: 5px;
  padding: 0 20px;
}

:deep(.el-step__head.is-process) {
  color: #409EFF;
  border-color: #409EFF;
}

:deep(.el-step__title.is-process) {
  color: #409EFF;
  font-weight: 600;
}

.box-card {
  margin-bottom: 20px;
}

.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-weight: 600;
}

.upload-actions {
  display: flex;
  gap: 12px;
  margin-bottom: 15px;
}

.file-list-container {
  min-height: 200px;
}

.file-item {
  display: flex;
  align-items: center;
  padding: 10px;
  border-bottom: 1px dashed #e6e8eb;
}

.file-item:last-child {
  border-bottom: none;
}

.file-icon {
  margin-right: 12px;
  color: #409eff;
  font-size: 18px;
}

.file-info {
  flex: 1;
}

.file-name {
  font-size: 14px;
  margin-bottom: 4px;
}

.file-size {
  font-size: 12px;
  color: #909399;
}

.no-file-tip {
  text-align: center;
  padding: 40px 20px;
  color: #909399;
}

.no-file-tip i {
  font-size: 24px;
  margin-bottom: 10px;
}

.no-file-tip p {
  margin: 0;
  font-size: 14px;
}

.server-card {
  margin-top: 20px;
}

.server-item {
  padding: 15px;
  border-bottom: 1px solid #f0f0f0;
}

.server-item:last-child {
  border-bottom: none;
}

.server-info {
  display: flex;
  align-items: center;
  gap: 15px;
  margin-bottom: 10px;
}

.server-name {
  font-weight: 600;
}

.server-address {
  color: #606266;
  font-size: 13px;
}

.file-progress-item {
  margin-bottom: 10px;
}

.file-progress-item:last-child {
  margin-bottom: 0;
}

.file-progress {
  display: flex;
  align-items: center;
  gap: 10px;
}

.file-progress .el-progress {
  flex: 1;
}

.progress-text {
  font-size: 12px;
  color: #606266;
  min-width: 120px;
}

.el-form-item__tip {
  font-size: 12px;
  color: #909399;
  margin-top: 4px;
}

.file-status {
  margin-right: 10px;
  display: flex;
  align-items: center;
  min-width: 60px;
  justify-content: center;
}

.status-icon {
  font-size: 18px;
}

.status-text {
  font-size: 12px;
  color: #909399;
}

.file-item {
  display: flex;
  align-items: center;
  padding: 10px;
  border-bottom: 1px dashed #e6e8eb;
  position: relative;
}

.file-progress-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 8px 0;
  border-bottom: 1px dashed #f0f0f0;
}

.file-progress-item:last-child {
  border-bottom: none;
}

.file-name {
  flex: 1;
  font-size: 13px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.file-status {
  margin-left: 10px;
  min-width: 60px;
  text-align: right;
}

.server-info {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 12px;
}

.server-name {
  font-weight: 600;
  min-width: 120px;
}

.server-address {
  color: #606266;
  font-size: 13px;
  flex: 1;
}
</style>